package com.example.demo;

import com.example.demo.mapper.CoffeeMapper;
import com.example.demo.mapper.OrderMapper;
import com.example.demo.model.Coffee;
import com.example.demo.model.Order;
//import com.github.pagehelper.PageInfo;
import com.example.demo.model.OrderState;
import com.example.demo.service.CoffeeOrderService;
import com.example.demo.service.CoffeeService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import io.lettuce.core.ReadFrom;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;
import javax.annotation.Resource;
import javax.sql.DataSource;

@SpringBootApplication
@EnableTransactionManagement
@Slf4j
@MapperScan("com.example.demo.mapper")
public class DemoApplication implements ApplicationRunner {

	@Autowired
	private OrderMapper orderMapper;
	@Resource
	private CoffeeMapper coffeeMapper;
	@Autowired
	private CoffeeService coffeeService;
	@Autowired
	private CoffeeOrderService coffeeOrderService;

	@Autowired
	private DataSource dataSource;
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Autowired
	private TransactionTemplate transactionTemplate;


	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}


//	@Bean
//	public RedisTemplate<String, Coffee> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//		RedisTemplate<String, Coffee> template = new RedisTemplate<>();
//		template.setConnectionFactory(redisConnectionFactory);
//		return template;
//	}

//	@Bean
//	public LettuceClientConfigurationBuilderCustomizer customizer() {
//		return builder -> builder.readFrom(ReadFrom.MASTER_PREFERRED);
//	}

	@Override
	public void run(ApplicationArguments args) throws Exception {
		orderMapper.findAllWithRowBounds(new RowBounds(0, 2))
				.forEach(o -> log.info("Page(1) Order {}", o));
		orderMapper.findAllWithRowBounds(new RowBounds(2, 3))
				.forEach(c -> log.info("Page(2) Order {}", c));

		log.info("===================");

		orderMapper.findAllWithRowBounds(new RowBounds(1, 0))
				.forEach(c -> log.info("Page(1) Order {}", c));

		log.info("===================");

		orderMapper.findAllWithParam(2,1)
				.forEach(c -> log.info("Page(2) Order {}", c));
		List<Order> list = orderMapper.findAllWithParam(1, 1);
//		Page<Order> pageOrder =orderMapper.findPage(2,1);
		PageInfo page = new PageInfo(list);
		log.info("PageInfo: {}", page);


		Coffee outc= null;
		//connect


		//find init Data by id=0L
		outc = coffeeMapper.findById(1L);
		log.info("find coffee by init id=1:{}",outc);

		log.info("transaction：count before transaction:{}",coffeeMapper.count());
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus status) {
				//insert
				Coffee c= Coffee.builder().name("xyz").price(12L).build();
				log.info("transaction：will insert one data :" + c.toString());
				int count = coffeeMapper.save(c);
				log.info("transaction：count in transaction:{}",coffeeMapper.count());
				status.setRollbackOnly();
			}
		});
		log.info("transaction：count after transaction rollback:{}",coffeeMapper.count());

		//insert
		Coffee c= Coffee.builder().name("xxx").price(10L).build();
		log.info("will insert one data :" + c.toString());
		int count = coffeeMapper.save(c);
		outc = coffeeMapper.findByName(c.getName());
		log.info("find coffee_insert by name:{}",outc);

		//存入redis-并查询
		Coffee c_r = coffeeService.findOneCoffee(outc.getName());
		log.info("Value from Redis: {}", c_r);
		//循环查询验证从redis取数据
		Coffee c_r2 = null;
		for (int i=1;i<3;i++){
			c_r2 = coffeeService.findOneCoffee(outc.getName());
			log.info("selected by name: {}", c_r);
		}


		//update
		Coffee c_up= Coffee.builder().name("xyz").price(23L).build();
		int count2 = coffeeMapper.update(c_up);
		outc = coffeeMapper.findByName(c_up.getName());
		log.info("find coffee_update by name:{}",outc);

		//delete
		int count3 = coffeeMapper.delete(c);
		outc = coffeeMapper.findByName(c.getName());
		log.info("find coffee_delete by name:{}",outc);

		//update state
		Order order = coffeeOrderService.createOrder("lisi",coffeeMapper.findByName("espresso"));
		coffeeOrderService.updateState(order, OrderState.BREWED);

		return;
	}
}
